package Region

import (
	"context"

	v1 "gitee.com/liangziyisheng/caas-platform-mc/api/region/v1"
	"gitee.com/liangziyisheng/caas-platform-mc/internal/consts"
	"gitee.com/liangziyisheng/caas-platform-mc/internal/dao"
	"gitee.com/liangziyisheng/caas-platform-mc/internal/model/do"
	"gitee.com/liangziyisheng/caas-platform-mc/internal/service"
	"gitee.com/liangziyisheng/caas-platform-mc/utility/cache"

	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/glog"
)

type sRegion struct{}

var l = g.Log("logger for Region")

func New() *sRegion {
	return &sRegion{}
}

func init() {
	l.SetFlags(glog.F_FILE_LONG)
	service.RegisterRegion(New())
}

func (s *sRegion) List(ctx context.Context, in *v1.ListInput) (out *v1.ListOutput, err error) {
	md := dao.Region.Ctx(ctx)
	cls := dao.Region.Columns()
	if in.Country != "" {
		md = md.Where(cls.Country, in.Country)
	}
	out = &v1.ListOutput{}
	err = md.Scan(&out.Data)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.ListRegionFailed, in))
	}
	return out, nil
}

func (s *sRegion) Countries(ctx context.Context) (out *v1.ListOutput, err error) {
	out = &v1.ListOutput{}
	err = dao.Region.Ctx(ctx).Where(dao.Region.Columns().Level, 1).Scan(&out.Data)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.ListRegionFailed)
	}
	return out, nil
}

func (s *sRegion) Add(ctx context.Context, in *v1.AddInput) (out *v1.AddOutput, err error) {
	l.Info(ctx, "region add")
	out = &v1.AddOutput{}
	out.Id, err = dao.Region.Ctx(ctx).InsertAndGetId(in.Region)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.AddFailed, in.Region))
	}
	// 设置缓存
	err = cache.InitCache(ctx, consts.InitialCacheKeys.RegionsKey, true)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.ResetRegionCacheFailed)
	}
	return out, nil
}

func (s *sRegion) Delete(ctx context.Context, in *v1.DeleteInput) (out *v1.DeleteOutput, err error) {
	// 先检查是否存在
	reg := &do.Region{}
	rows := 0
	err = dao.Region.Ctx(ctx).Where(dao.Region.Columns().Id, in.Id).ScanAndCount(&reg, &rows, true)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.ListRegionFailed, in.Id))
	}
	if rows == 0 {
		return nil, gerror.NewCode(gcode.WithCode(consts.RegionNotExist, in.Id))
	}
	// 先检查是否存在孩子节点
	sub, err := dao.Region.Ctx(ctx).Where(dao.Region.Columns().Parent, reg.Code).Count()
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.QueryRegionChildrenFailed, reg.Code))
	}
	if sub > 0 {
		return nil, gerror.NewCode(consts.IncludeAtLeastOneChild)
	}
	rs, err := dao.Region.Ctx(ctx).Where(dao.Region.Columns().Id, in.Id).Delete()
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.DeleteRegionFailed, in.Id))
	}
	out = &v1.DeleteOutput{}
	if out.Rows, err = rs.RowsAffected(); err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.DeleteRegionFailed, in.Id))
	}
	if out.Rows == 0 {
		return nil, gerror.NewCode(gcode.WithCode(consts.DeleteFailed, in.Id))
	}
	err = cache.InitCache(ctx, consts.InitialCacheKeys.RegionsKey, true)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.ResetRegionCacheFailed)
	}
	return out, nil
}

func (s *sRegion) Update(ctx context.Context, in *v1.UpdateInput) (out *v1.UpdateOutput, err error) {
	out = &v1.UpdateOutput{}
	out.Rows, err = dao.Region.Ctx(ctx).Data(in.Region).Where(dao.Region.Columns().Id, in.Id).UpdateAndGetAffected()
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(gcode.WithCode(consts.UpdateRegionFailed, in.Region))
	}
	if out.Rows == 0 {
		return nil, gerror.NewCode(gcode.WithCode(consts.UpdateFailed, in.Id))
	}
	err = cache.InitCache(ctx, consts.InitialCacheKeys.RegionsKey, true)
	if err != nil {
		l.Error(ctx, err)
		return nil, gerror.NewCode(consts.ResetRegionCacheFailed)
	}
	return out, nil
}
